#include "bootstrap.h"

Bootstrap::Bootstrap(QObject *parent) : QObject(parent)
{
    receiver=nullptr;
    dsTable=P_DATASOURCE;
}

void Bootstrap::start()
{
    if(!connectDB())
    {
        appendLog("DB CAN NOT Connected!!!");
        QCoreApplication::exit(DB_ERR);
        return;
    }

    updateDataSource();
    startTimer(AUTOSYNC_INTERVAL);
    startReceiver();
}

void Bootstrap::stop()
{
    stopReceiver();
}

bool Bootstrap::connectDB()
{
    QSettings reg(REG_BOOTSTRAP,QSettings::NativeFormat);
    QString host=reg.value("ds_host").toString();
    if(host.isEmpty())
        host="127.0.0.1";

    int port=3306;
    port=reg.value("ds_port").toInt();
    if(port==0)
        port=3306;

    QString user=reg.value("ds_user").toString();
    if(user.isEmpty())
        return false;

    QString passwd=reg.value("ds_passwd").toString();
    if(passwd.isEmpty())
        return false;

    QString dbName=reg.value("ds_db").toString();
    if(dbName.isEmpty())
        return false;

    db=getConnection(host,port,user,passwd,dbName,SP_NAME);
    if(db.open())
        return true;
    else
    {
        appendLog(db.lastError().text());
        return false;
    }
}

void Bootstrap::dbTry()
{
    if(!db.isOpen())
        db.open();
}

void Bootstrap::appendLog(const QString &event,
                          QtServiceBase::MessageType type)
{
    // 直接写到系统日志中，无需额外添加时间和名称
    QtServiceBase::instance()->logMessage(event,type);
}

void Bootstrap::timerEvent(QTimerEvent *)
{
    updateDataSource();
}

void Bootstrap::onReceived(const QByteArray data)
{
    QCborValue value=QCborValue::fromCbor(data);
    if(!value.isMap())
        return;

    QCborMap item=value.toMap();
    QString clientIP=item.value("ip").toString();
    QString entry=item.value("entry").toString();
    if(clientIP.isEmpty() || entry.isEmpty())
        return;

    QCborMap reply;
    if(dataSource.contains(entry))
        reply=dataSource.value(entry);
    else
        reply=fetchData(entry);

    sendReply(clientIP,reply);
}

void Bootstrap::sendReply(const QString &clientIP, const QCborMap &reply)
{
    QByteArray data=QCborValue(reply).toCbor();
    sp_sendData(data,clientIP,PORT_MESSAGE);
    appendLog(QString("%1, Delivered").arg(clientIP));
}

void Bootstrap::startReceiver()
{
    receiver=new BaseUdpReceiver(nullptr,PORT_COMPLEX,false);
    connect(receiver,&BaseUdpReceiver::received,
            this,&Bootstrap::onReceived);

    connect(&recvThread,&QThread::finished,
            receiver,&QObject::deleteLater);

    receiver->moveToThread(&recvThread);
    recvThread.start();
}

void Bootstrap::stopReceiver()
{
    recvThread.quit();
    recvThread.wait();
}

void Bootstrap::updateDataSource()
{
    if(!dataSource.isEmpty())
        dataSource.clear();

    dbTry();
    QSqlQuery query(db);
    query.exec(QString("select entry,host,port,user,passwd,db from %1")
               .arg(dsTable));
    while (query.next()) {
        QString entry=query.value(0).toString();
        if(entry.isEmpty())
            continue;

        QString host=query.value(1).toString();
        int port=query.value(2).toInt();
        if(port == 0)
            port=3306;
        QString user=query.value(3).toString();
        QString passwd=query.value(4).toString();
        QString db=query.value(5).toString();

        QCborMap item;
        item.insert(QString("entry"),entry);
        item.insert(QString("host"),host);
        item.insert(QString("port"),port);
        item.insert(QString("user"),user);
        item.insert(QString("passwd"),passwd);
        item.insert(QString("db"),db);

        dataSource.insert(entry,item);
    }
    db.close();

    appendLog(QString("Sync Finished, Count: %1").arg(dataSource.size()));
}

QCborMap Bootstrap::fetchData(const QString &entry)
{
    QCborMap item;
    dbTry();
    QSqlQuery query(db);
    query.exec(QString("select host,port,user,passwd,db from %1 where entry='%2'")
               .arg(dsTable)
               .arg(entry));
    if (query.next()) {
        QString host=query.value(0).toString();
        int port=query.value(1).toInt();
        if(port == 0)
            port=3306;
        QString user=query.value(2).toString();
        QString passwd=query.value(3).toString();
        QString db=query.value(4).toString();

        item.insert(QString("entry"),entry);
        item.insert(QString("host"),host);
        item.insert(QString("port"),port);
        item.insert(QString("user"),user);
        item.insert(QString("passwd"),passwd);
        item.insert(QString("db"),db);

        dataSource.insert(entry,item);
    }
    db.close();
    return item;
}


